默认布局组件:需求分析
进入布局组件开发之前,需要先对管理后台最经典的布局形态做完整的需求拆解。默认布局(DefaultLayout)是整个后台系统的骨架——左侧菜单 + 右侧内容区,几乎所有后台管理系统的核心页面都建立在这个布局之上。
布局结构分析
一个标准的管理后台布局由四个区域组成:
┌──────────────────────────────────────────────┐
│ 整个屏幕 │
├──────────┬───────────────────────────────────┤
│ │ Header(头部工具栏) │
│ │ ┌─────────────────────────────┐ │
│ Side │ │ 折叠按钮 | 面包屑 | 工具区 │ │
│ Menu │ └─────────────────────────────┘ │
│ ├───────────────────────────────────┤
│ │ │
│ (菜单) │ Content(RouterView) │
│ │ │
│ │ │
└──────────┴───────────────────────────────────┘
text
左侧 Side 区域放置 Menu 组件,右侧分为上下两部分:Header 存放工具类组件(折叠按钮、面包屑、暗黑模式、全屏、语言切换、头像菜单),Content 区域通过 RouterView 渲染当前路由对应的页面内容。
抽屉组件(Drawer)的定位
主题设置功能使用 Element Plus 的 el-drawer 组件实现。抽屉组件从屏幕右侧滑出,用户可以在其中配置主题颜色、暗黑模式、导航模式等设置项。
Drawer 的核心特性:
| 特性 | 说明 |
|---|---|
| 方向控制 | direction="rtl" 从右侧打开(默认值) |
| 触发方式 | 通常绑定一个 ref<boolean> 控制 v-model |
| 点击遮罩关闭 | close-on-click-modal 默认为 true |
| 自定义内容 | 通过 default 插槽放置任意内容 |
用 CSS 实现抽屉滑出效果的原理也很简单——transform: translateX(100%) 定位在右侧屏幕外,打开时通过过渡动画将 translateX 恢复为 0。
数据存储方案的选择
主题配置数据(颜色、模式、菜单宽度等)应该存储在哪里?有三种方案:
| 方案 | 优点 | 缺点 |
|---|---|---|
| Pinia Store | 全局共享,持久化方便 | 与状态管理强耦合,组件通用性降低 |
| Layout 组件内部 | 组件自包含,无外部依赖 | 切换 Layout 时数据丢失 |
| Provide/Inject | 组件间共享,不引入全局依赖 | 仅在组件树内有效 |
推荐方案:Layout 组件内部存储 + Provide/Inject 传递。 理由是:
- 基础组件不应直接依赖 Pinia,保持通用性。
- 通过
provide在 Layout 组件中提供主题数据,子组件通过inject获取。 - 如果用户需要持久化或跨 Layout 共享,可以在 Layout 外层将数据同步到 Pinia。
// 在 Layout 组件中 provide
provide('themeSettings', settings)
// 在子组件中 inject
const settings = inject('themeSettings')
typescript
依赖注入:Provide / Inject
Vue 的 provide 和 inject 类似于 React 的 Context API。父组件通过 provide 向下注入数据,任意层级的子组件通过 inject 获取,避免了逐层 props 传递的繁琐。
Layout(provide themeSettings)
├── Header(inject themeSettings)
│ ├── ThemeSetting(inject themeSettings)
│ └── AvatarMenu
├── Menu(inject iconProps)
│ ├── SubMenu
│ └── MenuItem
└── RouterView
text
关键点:provide 可以在应用级别使用(app.provide),也可以在组件级别使用。对于主题配置这种局部数据,在 Layout 组件中使用组件级别的 provide 更合适。
Layout 的基础模板结构
<!-- src/layouts/default.vue -->
<template>
<div class="w-full h-screen overflow-hidden flex">
<!-- 左侧菜单 -->
<aside :style="{ width: menuWidth }" class="h-full">
<el-scrollbar>
<Menu :data="menus" />
</el-scrollbar>
</aside>
<!-- 右侧内容区 -->
<div class="flex-1 h-full flex flex-col">
<Header />
<main class="flex-1 overflow-auto">
<RouterView />
</main>
</div>
</div>
</template>
vue
这个结构的特点是:最外层 flex 水平布局,左侧 aside 固定宽度,右侧 flex-1 自动填充剩余空间。右侧内部再使用 flex-col 垂直布局,Header 固定高度,Content 自动填充。
本节小结
需求分析阶段需要明确三个核心问题:
- 布局结构:左右分栏,右侧上下分区,这是管理后台最经典的三区布局。
- 数据流:主题配置使用
provide/inject在 Layout 组件树内传递,不直接引入 Pinia。 - 组件边界:Drawer(抽屉)作为主题设置的容器,Header 集成工具栏,Content 通过 RouterView 渲染页面。
下一节将实现自动路由形成基础菜单结构,把 Vue Router 的路由配置转换为 Menu 组件所需的 AppRouteMenuItem 数据格式。
↑